using System.Collections;
using System.Collections.Generic;
using System.Net.Mime;
using Ants.Utilities;
using UnityEngine;
using UnityEngine.Experimental.Rendering.Universal;
using Debug = Ants.Utilities.Debug;

[RequireComponent(typeof(PolygonCollider2D))]
public class PolygonShadowCollider : ShadowCollider
{
    public LayerMask rayCasterLayer;
    
    private EdgeCollider2D _shadowCollider = null;
    private EdgeCollider2D shadowCollider
    {
        get
        {
            if (_shadowCollider == null)
            {
                _shadowCollider = GetComponentInChildren<EdgeCollider2D>();

                if (_shadowCollider == null)
                {
                    GameObject go=new GameObject("ShadowCollider");
                    go.layer =(int) Consts.ELayer.ShadowCollider;
                    _shadowCollider = go.AddComponent<EdgeCollider2D>();
                    go.transform.SetParent(transform,false);
                    if (go.GetComponent<Rigidbody2D>() == null)
                    {
                        Rigidbody2D rb=go.AddComponent<Rigidbody2D>();
                        rb.bodyType = RigidbodyType2D.Static;
                    }
                }
                    
                

            }
            return _shadowCollider;
        }
    }

    private PolygonCollider2D _collider = null;
    private PolygonCollider2D collider
    {
        get
        {
            if (_collider == null)
            {
                _collider = GetComponent<PolygonCollider2D>();
            }
            return _collider;
        }
    }
    /**
     * 注意！！！！！！！套用该组件的对象不可以改Scale，也就是说Scale必须保持为1，1，1，否则多边形碰撞组件会出编辑显示错误
     */
    private void GenCollider()
    {
        List<Vector2> ps=new List<Vector2>(4);
        TangentInfo2D t1, t2;
        Geometry2D.GetMinSector(light.transform.position,new Polygon2D(collider.points,collider.transform), out t1,out t2);
        ps.Add(t1.worldPos);
        ps.Add(t2.worldPos);
        RaycastHit2D hit3 = Physics2D.Raycast(t2.worldPos, t2.dir,rayCastDist,rayCasterLayer.value);
        Vector2 p3 =hit3.transform!=null? hit3.point : t2.worldPos + t2.dir * rayCastDist;
        RaycastHit2D hit4 = Physics2D.Raycast(t1.worldPos, t1.dir,rayCastDist,rayCasterLayer.value);
        Vector2 p4 = hit4.transform!=null? hit4.point : t1.worldPos + t1.dir * rayCastDist;
        ps.Add(p3);
        ps.Add(p4);
        ps.Add(t1.worldPos);
        var po=new Polygon2D(ps.ToArray());
        po.InverseTransformBy(collider.transform);
        shadowCollider.SetPoints(new List<Vector2>(po.points));
        shadowCollider.edgeRadius = edgeColliderThick;
    }
    void Update()
    {
        if (caster != null && caster.castsShadows && !isShadowCulled())
        {
            GenCollider();
        }
        
    }
    private void OnDrawGizmos()
    {
        
        TangentInfo2D t1, t2;
        Polygon2D po = new Polygon2D(collider.points, collider.transform);
        foreach (var p in po.points)
        {
            Gizmos.DrawSphere(p,0.01f);
        }
        Geometry2D.GetMinSector(light.transform.position,po, out t1,out t2);
        RaycastHit2D hit3 = Physics2D.Raycast(t2.worldPos, t2.dir,rayCastDist,rayCasterLayer.value);
        Vector2 p3 =hit3.transform!=null? hit3.point : t2.worldPos + t2.dir * rayCastDist;
        RaycastHit2D hit4 = Physics2D.Raycast(t1.worldPos, t1.dir,rayCastDist,rayCasterLayer.value);
        Vector2 p4 = hit4.transform!=null? hit4.point : t1.worldPos + t1.dir * rayCastDist;
        Gizmos.DrawLine(t1.worldPos,t2.worldPos);
        Gizmos.DrawLine(t2.worldPos,p3);
        Gizmos.DrawLine(p3,p4);
        Gizmos.DrawLine(p4,t1.worldPos);
        
    }

}






/*---------------------------------------------射线版本，因为不稳定已废弃
using System.Collections.Generic;
using System.Net.Mime;
using Ants.Utilities;
using UnityEngine;
using UnityEngine.Experimental.Rendering.Universal;
using Debug = Ants.Utilities.Debug;

[RequireComponent(typeof(PolygonCollider2D))]
public class PolygonShadowCollider : ShadowCollider
{
    public LayerMask rayCasterLayer;
    
    
    [Space]
    [Header("factors below is only controlled by master")]
    public float pointMatchTolerence = 1f;
    public float pointSquizerIntensity = 0.001f;
    public float tendToSpaceDither = 0.01f;
    private EdgeCollider2D _shadowCollider = null;
    private EdgeCollider2D shadowCollider
    {
        get
        {
            if (_shadowCollider == null)
            {
                _shadowCollider = GetComponentInChildren<EdgeCollider2D>();

                if (_shadowCollider == null)
                {
                    GameObject go=new GameObject("ShadowCollider");
                    go.layer =(int) Consts.ELayer.ShadowCollider;
                    _shadowCollider = go.AddComponent<EdgeCollider2D>();
                    go.transform.SetParent(transform,false);
                    if (go.GetComponent<Rigidbody2D>() == null)
                    {
                        Rigidbody2D rb=go.AddComponent<Rigidbody2D>();
                        rb.bodyType = RigidbodyType2D.Static;
                    }
                }
                    
                

            }
            return _shadowCollider;
        }
    }

    private PolygonCollider2D _collider = null;
    private PolygonCollider2D collider
    {
        get
        {
            if (_collider == null)
            {
                _collider = GetComponent<PolygonCollider2D>();
            }
            return _collider;
        }
    }

    private List<Vector2> GetShadowColliderPolygon(Vector2 projectorPos, Polygon2D polygon2D)
    {
        List<Vector2> shadowColliderPoints=new List<Vector2>();
        Vector2 anchor = new Vector2(collider.transform.position.x, collider.transform.position.y);

        TangentInfo2D[] tangentInfo2Ds = new TangentInfo2D[2];
        RaycastHit2D[] outHits = new RaycastHit2D[2];
        int index = 0;
        foreach (var  lp in polygon2D.points)
        {
            Vector2 squize = (polygon2D.geomCenter-lp).normalized;
            Vector2 p =lp+squize*pointSquizerIntensity+anchor;
            Vector2 dir = (p-projectorPos);

            RaycastHit2D hM = Physics2D.Raycast(projectorPos, dir, rayCastDist,rayCasterLayer);//layer必须保证能射中自身
            if (Math.PointMatch(p,hM.point,pointMatchTolerence*0.001f))
            {
                int matches=0;
                float dither = tendToSpaceDither;
                Vector2 rotDP = Geometry2D.RotVec2(dir, dither);
                Vector2 rotDN = Geometry2D.RotVec2(dir, -dither);
                bool hACHitSelf=false;
                RaycastHit2D hAC = Physics2D.Raycast(projectorPos, rotDP, rayCastDist,rayCasterLayer);//layer保证射中能阻挡光线的物体
                UnityEngine.Debug.DrawRay(projectorPos,rotDP,Color.black);
                RaycastHit2D hC = Physics2D.Raycast(projectorPos, rotDN, rayCasterLayer);
                UnityEngine.Debug.DrawRay(projectorPos,rotDN,Color.yellow);
                bool isThat = false;
                if (hAC.transform!=null && hAC.transform.gameObject == gameObject)
                {
                    matches++;
                    isThat = true;
                }
                if (hC.transform!=null && hC.transform.gameObject == gameObject)
                {
                    matches++;
                }
                if (matches == 1)
                {
                    tangentInfo2Ds[index]=new TangentInfo2D(p,dir);
                    outHits[index] = isThat ? hC : hAC;
                    index++;
                    if (index == 2) break;
                    
                    
                }
                    
                
            }

        }
        shadowColliderPoints.Add( tangentInfo2Ds[0].worldPos-anchor);
        shadowColliderPoints.Add((outHits[0].transform!=null?outHits[0].point:projectorPos + tangentInfo2Ds[0].dir * rayCastDist )-anchor);
        shadowColliderPoints.Add((outHits[1].transform!=null?outHits[1].point:projectorPos + tangentInfo2Ds[1].dir * rayCastDist )-anchor);
        shadowColliderPoints.Add( tangentInfo2Ds[1].worldPos-anchor);
        
        return shadowColliderPoints;
    }

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if (caster != null && caster.castsShadows && !isShadowCulled())
        {
            var path = GetShadowColliderPolygon(light.transform.position, new Polygon2D(collider.points));
            Painter.color=Color.blue;
            Painter.DrawPath(Vector2.zero,path.ToArray());
            shadowCollider.SetPoints(path);
        }
    }
    private void OnDrawGizmos()
    {
        Polygon2D polygon2D=new Polygon2D(collider.points);
        Vector2 projectorPos = light.transform.position;
               List<Vector2> shadowColliderPoints=new List<Vector2>();
        Vector2 anchor = new Vector2(collider.transform.position.x, collider.transform.position.y);

        TangentInfo2D[] tangentInfo2Ds = new TangentInfo2D[2];
        RaycastHit2D[] outHits = new RaycastHit2D[2];
        int index = 0;
        foreach (var  lp in polygon2D.points)
        {
            Vector2 squize = (polygon2D.geomCenter-lp).normalized;
            Vector2 p =lp+squize*pointSquizerIntensity+anchor;
            Vector2 dir = (p-projectorPos);

            RaycastHit2D hM = Physics2D.Raycast(projectorPos, dir, rayCastDist,rayCasterLayer);//layer必须保证能射中自身
            Gizmos.DrawSphere(new Vector3(hM.point.x,hM.point.y,0f),0.01f);
            if (Math.PointMatch(p,hM.point,pointMatchTolerence*0.001f))
            {
                int matches=0;
                float dither = tendToSpaceDither;
                Vector2 rotDP = Geometry2D.RotVec2(dir, dither);
                Vector2 rotDN = Geometry2D.RotVec2(dir, -dither);
                bool hACHitSelf=false;
                RaycastHit2D hAC = Physics2D.Raycast(projectorPos, rotDP, rayCastDist,rayCasterLayer);//layer保证射中能阻挡光线的物体
                UnityEngine.Debug.DrawRay(projectorPos,rotDP,Color.black);
                RaycastHit2D hC = Physics2D.Raycast(projectorPos, rotDN, rayCasterLayer);
                UnityEngine.Debug.DrawRay(projectorPos,rotDN,Color.yellow);
                bool isThat = false;
                if (hAC.transform!=null && hAC.transform.gameObject == gameObject)
                {
                    matches++;
                    isThat = true;
                }
                if (hC.transform!=null && hC.transform.gameObject == gameObject)
                {
                    matches++;
                }
                if (matches == 1)
                {
                    tangentInfo2Ds[index]=new TangentInfo2D(p,dir);
                    outHits[index] = isThat ? hC : hAC;
                    index++;
                    if (index == 2) break;
                    
                    
                }
                    
                
            }

        }
        float r = 0.01f;
        Vector2 p1 = tangentInfo2Ds[0].worldPos;
        Vector2 p2 = outHits[0].transform != null
            ? outHits[0].point
            : projectorPos + tangentInfo2Ds[0].dir * rayCastDist;
        Vector2 p3 = (outHits[1].transform != null
            ? outHits[1].point
            : projectorPos + tangentInfo2Ds[1].dir * rayCastDist);
        Vector2 p4 = tangentInfo2Ds[1].worldPos;
        Gizmos.DrawLine(p1,p2);
        Gizmos.DrawLine(p2,p3);
        Gizmos.DrawLine(p3,p4);
        Gizmos.DrawLine(p4,p1);

    }
}

----------------------------------*/